package com.zheng.api.server.service.mq.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.zheng.api.server.service.base.pay.Base4RefundOrderService;
import com.zheng.api.server.service.base.pay.BaseNotify4MchRefund;
import com.zheng.api.server.service.base.pay.PayChannel4AliService;
import com.zheng.api.server.service.base.pay.PayChannel4WxService;
import com.zheng.common.constant.MqConstant;
import com.zheng.common.constant.PayConstant;
import com.zheng.common.util.RpcUtil;
import com.zheng.common.util.StringUtil;
import com.zheng.pay.dao.model.PayRefundOrder;
import com.zheng.pay.dao.model.PayRefundOrderExample;
import com.zheng.pay.rpc.api.PayRefundOrderService;
import org.apache.activemq.ScheduledMessage;
import org.apache.activemq.command.ActiveMQQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessageCreator;
import org.springframework.stereotype.Service;

import javax.jms.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 业务通知MQ实现
 * @author lvb
 * @date 2017-10-30
 * @version V1.0
 * @Copyright:
 */
@Service
public class Mq4RefundNotify extends Base4RefundOrderService {

    private Queue refundNotifyQueue =new ActiveMQQueue(MqConstant.ZHENG_SERVER_QUEUE_PAY_NOTIFY_REFUND_NAME);;

    @Autowired
    private JmsTemplate jmsQueueTemplate;

    @Autowired
    private PayChannel4WxService payChannel4WxService;

    @Autowired
    private PayChannel4AliService payChannel4AliService;

    @Autowired
    private BaseNotify4MchRefund baseNotify4MchRefund;

    @Autowired
    private PayRefundOrderService payRefundOrderService;

    private static final Logger LOGGER = LoggerFactory.getLogger(Mq4RefundNotify.class);

    public void send(String msg) {
        LOGGER.info("发送MQ消息:msg={}", msg);
        this.jmsQueueTemplate.convertAndSend(this.refundNotifyQueue, msg);
    }

    /**
     * 发送延迟消息
     * @param msg
     * @param delay
     */
    public void send(final String msg, final long delay) {
        LOGGER.info("发送MQ延时消息:msg={},delay={}", msg, delay);
        jmsQueueTemplate.send(this.refundNotifyQueue, new MessageCreator() {
            public Message createMessage(Session session) throws JMSException {
                TextMessage tm = session.createTextMessage(msg);
                tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY, delay);
                tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_PERIOD, 1*1000);
                tm.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_REPEAT, 1);
                return tm;
            }
        });
    }

    @JmsListener(destination = MqConstant.ZHENG_SERVER_QUEUE_PAY_NOTIFY_REFUND_NAME)
    public void receive(String msg) {
        LOGGER.info("处理退款任务.msg={}", msg);
        JSONObject msgObj = JSON.parseObject(msg);
        String refundOrderId = msgObj.getString("refundorderid");
        String channelName = msgObj.getString("channelname");

        PayRefundOrderExample refundOrderExample = new PayRefundOrderExample();
        PayRefundOrderExample.Criteria refundOrdercriteria = refundOrderExample.createCriteria();
        refundOrdercriteria.andRefundorderidEqualTo(refundOrderId);
        PayRefundOrder refundOrder1 = payRefundOrderService.selectFirstByExample(refundOrderExample);

        if(refundOrder1 == null) {
            LOGGER.warn("查询退款订单为空,不能退款.refundorderid={}", refundOrderId);
            return;
        }
        if(refundOrder1.getStatus() != PayConstant.REFUND_STATUS_INIT) {
            LOGGER.warn("退款状态不是初始({})或失败({}),不能退款.refundorderid={}", PayConstant.REFUND_STATUS_INIT, PayConstant.REFUND_STATUS_FAIL, refundOrderId);
            return;
        }

        PayRefundOrder refundOrder = new PayRefundOrder();
        refundOrder.setStatus(PayConstant.REFUND_STATUS_REFUNDING);
        refundOrder.setRefundsucctime(new Date());
        PayRefundOrderExample example = new PayRefundOrderExample();
        PayRefundOrderExample.Criteria criteria = example.createCriteria();
        criteria.andRefundorderidEqualTo(refundOrderId);
        criteria.andStatusEqualTo(PayConstant.REFUND_STATUS_INIT);
        int result = payRefundOrderService.updateByExampleSelective(refundOrder, example);

        if(result != 1) {
            LOGGER.warn("更改退款为退款中({})失败,不能退款.refundorderid={}", PayConstant.REFUND_STATUS_REFUNDING, refundOrderId);
            return;
        }
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("refundOrder", refundOrder1);
        String jsonParam = RpcUtil.createBaseParam(paramMap);
        Map resultMap;
        if(PayConstant.CHANNEL_NAME_WX.equalsIgnoreCase(channelName)) {
            resultMap = payChannel4WxService.doWxRefundReq(jsonParam);
        }else if(PayConstant.CHANNEL_NAME_ALIPAY.equalsIgnoreCase(channelName)) {
            resultMap = payChannel4AliService.doAliRefundReq(jsonParam);
        }else {
            LOGGER.warn("不支持的退款渠道,停止退款处理.refundorderid={},channelName={}", refundOrderId, channelName);
            return;
        }
        if(!RpcUtil.isSuccess(resultMap)) {
            LOGGER.warn("发起退款返回异常,停止退款处理.refundorderid={}", refundOrderId);
            return;
        }
        Map bizResult = (Map) resultMap.get("bizResult");
        Boolean isSuccess = false;
        if(bizResult.get("isSuccess") != null) isSuccess = Boolean.parseBoolean(bizResult.get("isSuccess").toString());
        if(isSuccess) {
            // 更新退款状态为成功
            String channelOrderNo = StringUtil.toString(bizResult.get("channelorderno"));
            result = baseUpdateStatus4Success(refundOrderId, channelOrderNo);
            LOGGER.info("更新退款订单状态为成功({}),refundorderid={},返回结果:{}", PayConstant.REFUND_STATUS_SUCCESS, refundOrderId, result);
            // 发送商户通知
            refundOrder1.setStatus(PayConstant.REFUND_STATUS_SUCCESS);
            baseNotify4MchRefund.doNotify(refundOrder1, true);
        }else {
            // 更新退款状态为失败
            String channelErrCode = StringUtil.toString(bizResult.get("channelErrCode"));
            String channelErrMsg = StringUtil.toString(bizResult.get("channelErrMsg"));
            result = baseUpdateStatus4Fail(refundOrderId, channelErrCode, channelErrMsg);
            LOGGER.info("更新退款订单状态为失败({}),refundorderid={},返回结果:{}", PayConstant.REFUND_STATUS_FAIL, refundOrderId, result);
            // 发送商户通知
            refundOrder1.setStatus(PayConstant.REFUND_STATUS_FAIL);
            baseNotify4MchRefund.doNotify(refundOrder1, true);
        }

    }
}
